<template>
  <div>
    <div class="header">
      <h2>Vue CropperJS</h2>
      <a href="https://github.com/Agontuk/vue-cropperjs">Github</a>
    </div>
    <hr />

    <input
      ref="input"
      type="file"
      name="image"
      accept="image/*"
      @change="setImage"
    />

    <div class="content">
      <section class="cropper-area">
        <div class="img-cropper" style="height: 350px">
          <img
            v-show="imgSrc"
            ref="image"
            style="max-width: 100%"
            :src="imgSrc"
          />
          <div v-show="!imgSrc" class="cropper-placeholder"></div>
        </div>
        <div class="actions">
          <a href="#" role="button" @click.prevent="zoom(0.2)"> 放大 </a>
          <a href="#" role="button" @click.prevent="zoom(-0.2)"> 缩小 </a>
          <a href="#" role="button" @click.prevent="move(-10, 0)"> 左移 </a>
          <a href="#" role="button" @click.prevent="move(10, 0)"> 右移 </a>
          <a href="#" role="button" @click.prevent="move(0, -10)">上移</a>
          <a href="#" role="button" @click.prevent="move(0, 10)">下移</a>
          <a href="#" role="button" @click.prevent="rotate(90)"> 旋转+90度 </a>
          <a href="#" role="button" @click.prevent="rotate(-90)"> 旋转-90度 </a>
          <a ref="flipXRef" href="#" role="button" @click.prevent="flipX">
            翻转X轴
          </a>
          <a ref="flipYRef" href="#" role="button" @click.prevent="flipY">
            翻转Y轴
          </a>
          <a href="#" role="button" @click.prevent="cropImage"> 裁剪 </a>
          <a href="#" role="button" @click.prevent="reset"> 重置 </a>
          <a href="#" role="button" @click.prevent="getData">获取数据 </a>
          <a href="#" role="button" @click.prevent="setData"> 写入数据 </a>
          <a href="#" role="button" @click.prevent="getCropBoxData">
            获取CropBox数据
          </a>
          <a href="#" role="button" @click.prevent="setCropBoxData">
            设置CropBox数据
          </a>
          <a href="#" role="button" @click.prevent="showFileChooser">
            上传图片
          </a>
        </div>

        <textarea v-model="data" />
      </section>
      <section class="preview-area">
        <p>预览</p>
        <div class="preview" />
        <p>裁剪的图像</p>
        <div class="cropped-image">
          <img v-if="cropImg" :src="cropImg" alt="Cropped Image" />
          <div v-else class="crop-placeholder" />
        </div>
      </section>
    </div>
  </div>
</template>

<script setup lang="ts">
import { onMounted, ref } from 'vue';
import Cropper from 'cropperjs';
import 'cropperjs/dist/cropper.css';

const image = ref<HTMLImageElement>();
const cropper = ref<Cropper>();
const flipXRef = ref();
const flipYRef = ref();
const input = ref();
const data = ref();
const imgSrc = ref('src/assets/wlf.png');
const cropImg = ref('');

function cropImage() {
  // get image data for post processing, e.g. upload or setting image src
  if (!cropper.value) return;
  cropImg.value = cropper.value.getCroppedCanvas().toDataURL();
}
function flipX() {
  const dom = flipXRef.value;
  let scale = dom.getAttribute('data-scale');
  scale = scale ? -scale : -1;
  cropper.value?.scaleX(scale);
  dom.setAttribute('data-scale', scale);
}
function flipY() {
  const dom = flipYRef.value;
  let scale = dom.getAttribute('data-scale');
  scale = scale ? -scale : -1;
  cropper.value?.scaleY(scale);
  dom.setAttribute('data-scale', scale);
}
function getCropBoxData() {
  data.value = JSON.stringify(cropper.value?.getCropBoxData(), null, 4);
}
function getData() {
  data.value = JSON.stringify(cropper.value?.getData(), null, 4);
}
function move(offsetX: number, offsetY: number) {
  cropper.value?.move(offsetX, offsetY);
}
function reset() {
  cropper.value?.reset();
}
function rotate(deg: number) {
  cropper.value?.rotate(deg);
}
function setCropBoxData() {
  if (!data.value) return;

  cropper.value?.setCropBoxData(JSON.parse(data.value));
}
function setData() {
  if (!data.value) return;

  cropper.value?.setData(JSON.parse(data.value));
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function setImage(e: any) {
  const file = e.target?.files[0];

  if (file.type.indexOf('image/') === -1) {
    alert('Please select an image file');
    return;
  }

  if (typeof FileReader === 'function') {
    const reader = new FileReader();
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    reader.onload = (event: any) => {
      if (!event.target) return;
      imgSrc.value = event.target.result;
      cropper.value?.replace(event.target.result);
    };
    reader.readAsDataURL(file);
  } else {
    alert('Sorry, FileReader API not supported');
  }
}
function showFileChooser() {
  input.value?.click();
}
function zoom(percent: number) {
  cropper.value?.zoom(percent);
}

onMounted(() => {
  if (!image.value) return;
  cropper.value = new Cropper(image.value, {
    preview: '.preview',
  });
});
</script>

<style scoped>
body {
  font-family: Arial, Helvetica, sans-serif;
  width: 1024px;
  margin: 0 auto;
}

input[type='file'] {
  display: none;
}

.header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 10px 0 5px 0;
}

.header h2 {
  margin: 0;
}

.header a {
  text-decoration: none;
  color: black;
}

.content {
  display: flex;
  justify-content: space-between;
}

.cropper-area {
  width: 614px;
}

.actions {
  margin-top: 1rem;
}

.actions a {
  display: inline-block;
  padding: 5px 15px;
  background: #0062cc;
  color: white;
  text-decoration: none;
  border-radius: 3px;
  margin-right: 1rem;
  margin-bottom: 1rem;
}

textarea {
  width: 100%;
  height: 100px;
}

.preview-area {
  width: 307px;
}

.preview-area p {
  font-size: 1.25rem;
  margin: 0;
  margin-bottom: 1rem;
}

.preview-area p:last-of-type {
  margin-top: 1rem;
}

.preview {
  width: 100%;
  height: calc(372px * (9 / 16));
  overflow: hidden;
}

.crop-placeholder {
  width: 100%;
  height: 200px;
  background-color: rgb(79, 78, 78);
}
.cropper-placeholder {
  width: 100%;
  height: 100%;
  background-color: rgb(79, 78, 78);
}

.cropped-image img {
  max-width: 100%;
}
</style>
